home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Experimental BBS Explossion 3
/
Experimental BBS Explossion III.iso
/
gus
/
miditest.zip
/
MIDITEST.CPP
next >
Wrap
C/C++ Source or Header
|
1993-03-28
|
7KB
|
316 lines
/* Gravis Ultrasound MIDI port test program */
/* Copyright 1993 Dave Perry */
/* This program may be used for non-commercial purposes only */
#include <dos.h>
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#pragma inline
#define CONTROL 0x100 /* Control port offset */
#define DATA 0x101 /* Data port offset */
#define BUFSIZE 512 /* Ring buffer */
#define PIC_MASK 0x21 /* 8259 interrupt mask port */
#define PIC_MASK2 0xa1 /* Secondary 8259 mask port */
unsigned char buffer[BUFSIZE];
unsigned char *head = buffer;
unsigned char *tail = buffer;
unsigned int base; /* Card base address */
void interrupt ( *old_isr)(...);
/*
status byte meaning data bytes
0x80-0x8f note off 2 - 1 byte pitch, followed by 1 byte velocity
0x90-0x9f note on 2 - 1 byte pitch, followed by 1 byte velocity
0xa0-0xaf key pressure 2 - 1 byte pitch, 1 byte pressure (after-touch)
0xb0-0xbf parameter 2 - 1 byte parameter number, 1 byte setting
0xc0-0xcf program 1 byte program selected
0xd0-0xdf chan. pressure 1 byte channel pressure (after-touch)
0xe0-0xef pitch wheel 2 bytes gives a 14 bit value, least significant
7 bits first
*/
enum status_t {UNKNOWN = 0,
NOTE_OFF = 0x80,
NOTE_ON = 0x90,
KEY_PRES = 0xa0,
PARM = 0xb0,
PROGRAM = 0xc0,
CHAN_PRES= 0xd0,
PITCH = 0xe0,
SYSEX = 0xf0};
char *keyname[] = {
"C ",
"C# ",
"D ",
"D# ",
"E ",
"F ",
"F# ",
"G ",
"G# ",
"A ",
"A# ",
"B "
};
void decode(unsigned char *message)
{
printf("| ");
if((message[0] & 0xf0) != SYSEX)
printf("Ch.%-2d ",(message[0] & 0x0f) + 1);
switch(message[0] & 0xf0){
case UNKNOWN:
printf("Unknown message");
break;
case NOTE_OFF:
printf("Note Off %d%s Vel: %d",
message[1]/12,keyname[message[1] % 12],message[2]);
break;
case NOTE_ON:
printf("Note On %d%s Vel: %d",
message[1]/12,keyname[message[1] % 12],message[2]);
break;
case KEY_PRES:
printf("Key Pres. %d%s Pressure: %d",
message[1]/12,keyname[message[1] % 12],message[2]);
break;
case PARM:
printf("Parameter %d Setting: %d",message[1],message[2]);
break;
case PROGRAM:
printf("Program %d",message[1]);
break;
case CHAN_PRES:
printf("Ch Press. %d",message[1]);
break;
case PITCH:
printf("P. Wheel %d",(message[1]+(message[2] << 7)) - 8192);
break;
case SYSEX:
printf("System");
break;
default:
;
}
}
void
showbyte(unsigned char abyte)
{
static status_t cur_status = UNKNOWN;
static int arg_cnt = 0;
static unsigned char message[3];
if(abyte & 0x80) { /* It's a status byte */
if((abyte < 0xf8)){ /* Ignore "real time" bytes */
printf("\n%2x ",abyte); /* Start new line, print status byte */
cur_status = (status_t)(abyte & 0xf0);
message[0] = abyte;
arg_cnt = 0;
}
} else { /* Not a status byte */
switch(cur_status) {
case UNKNOWN:
case NOTE_OFF:
case NOTE_ON:
case KEY_PRES:
case PARM:
case PITCH:
case SYSEX:
if((++arg_cnt % 2) && (arg_cnt != 1))
printf("\n %02x ",abyte);
else
printf("%02x ",abyte);
if((arg_cnt + 1) % 2) {
message[2] = abyte;
decode(message);
} else
message[1] = abyte;
break;
case PROGRAM:
case CHAN_PRES:
if(arg_cnt++)
printf("\n %02x ");
else
printf("%02x ",abyte);
message[1] = abyte;
decode(message);
break;
} /* switch */
} /* else */
}
void
send_eoi()
{
asm mov al,0bh; /* read in-service register from */
asm out 0a0h,al; /* secondary 8259 */
asm nop; /* settling delay */
asm nop
asm nop
asm in al,0a0h; /* get it */
asm or al,al; /* Any bits set? */
asm jz lab1; /* nope, not a secondary interrupt */
asm mov al,20h; /* Get EOI instruction */
asm out 0a0h,al; /* Secondary 8259 */
lab1: asm mov al,20h; /* 8259 end-of-interrupt command */
asm out 20h,al; /* Primary 8259 */
}
/* MIDI input interrupt handler */
void interrupt
midi_isr(...)
{
static cnt = 0;
*head = inportb(base+DATA); /* Grab the data */
asm cli;
if(cnt == BUFSIZE - 1) {/* Adjust the buffer pointer */
cnt = 0;
head = buffer;
} else {
++head;
++cnt;
}
asm sti;
send_eoi();
}
/* Pull a byte from the buffer */
unsigned char
pullbyte(void)
{
static cnt = 0;
unsigned char retval;
asm cli; /* Ints off for pointer manipulation */
if (head != tail)
{
retval = *tail++;
cnt++;
if(cnt == BUFSIZE) {
cnt = 0;
tail = buffer;
}
}
asm sti;
return(retval);
}
void
hook_irq(unsigned char irq)
{
unsigned char abyte,int_mask,vector;
unsigned int pic_mask; /* Address of PIC mask */
if(irq < 8){
vector = irq + 8;
pic_mask = PIC_MASK;
int_mask = 1 << irq;
}
else {
vector = irq + 0x70 - 8;
pic_mask = PIC_MASK2;
int_mask = 1 << (irq - 8);
}
/* save the existing interrupt vector */
old_isr = getvect(vector);
/* Install our interrupt vector */
setvect(vector,midi_isr);
/* Enable interrupts on the MIDI UART */
outportb(base+CONTROL,0x95);
/* Set up the 8259 PIC chip */
abyte = inportb(pic_mask); /* Read 8259 mask */
abyte &= ~int_mask; /* Clear mask for desired IRQ */
outportb(pic_mask,abyte);
}
void
unhook_irq(unsigned char irq)
{
unsigned char abyte, int_mask, vector;
unsigned int pic_mask;
if(irq < 8){
vector = irq + 8;
pic_mask = PIC_MASK;
int_mask = 1 << irq;
}
else {
vector = irq + 0x70 - 8;
pic_mask = PIC_MASK2;
int_mask = 1 << (irq - 8);
}
/* Mask the interrupt we hooked */
abyte = inportb(pic_mask); /* Read 8259 mask */
abyte |= int_mask; /* Set mask for desired IRQ */
outportb(pic_mask,abyte);
/* Restore old interrupt handler */
setvect(vector,midi_isr);
}
main()
{
int abyte;
char *envstring;
unsigned int midi_irq,dummy;
envstring = getenv("ULTRASND");
if(envstring == NULL) {
printf("ULTRASND environment string not found\n");
printf("Check your Ultrasound setup\n");
exit(0);
}
sscanf(envstring,"%x,%d,%d,%d,%d",
&base,&dummy,&dummy,&dummy,&midi_irq);
hook_irq(midi_irq);
printf("\nGravis Ultrasound MIDI Tester V1.0");
printf("\nCopyright 1993 Dave Perry");
printf("\nYour current setup is Base = %x, MIDI IRQ = %d",base,midi_irq);
printf("\nReading MIDI input - press any key to exit\n");
while (!kbhit()){
if(head != tail) { /* If new byte available */
abyte = pullbyte();
/* MIDI Thru */
while(!(inportb(base+CONTROL) & 0x02))
;
outportb(base+DATA,abyte);
showbyte(abyte);
}
}
printf("\n");
unhook_irq(midi_irq);
return 0;
}